//
// Created by 215609 on 2024/7/2.
//

#include "TSAudio.h"
#include "AndroidLog.h"
#include "libswresample/swresample.h"


TSAudio::~TSAudio() {


}
//播放   喇叭需要取出数据   ---》播放  主动了   孩子    肚子饿    不断吃
//  喇叭  --- pcmBufferCallBack 主动调用
void pcmBufferCallBack(SLAndroidSimpleBufferQueueItf bf,void *context){
    LOGE("-------->pcmBufferCallBack ");

    TSAudio *tsAudio=(TSAudio *)context;
    if (tsAudio!=NULL){
        int buffersize=tsAudio->resampleAudio();
        LOGE("-------->pcmBufferCallBack %d",buffersize);
        if(buffersize > 0){
          tsAudio->clock+=buffersize/((double)(tsAudio->sample_rate * 2 * 2));
            if (tsAudio->clock-tsAudio->last_tiem>= 0.1){
                tsAudio->last_tiem=tsAudio->clock;
                tsAudio->callJava->onCallTimeInfo(CHILD_THREAD,tsAudio->clock,tsAudio->duration);
            }
            (*tsAudio->pcmBufferQueue)->Enqueue(tsAudio->pcmBufferQueue, tsAudio->buffer,
                                                buffersize);
            LOGE("-------->pcmBufferCallBack %d",buffersize);
        }
    }
}



int TSAudio::getCurrentSampleRateForOpensles(int sample_rate) {
    int rate = 0;
    switch (sample_rate)
    {
        case 8000:
            rate = SL_SAMPLINGRATE_8;
            break;
        case 11025:
            rate = SL_SAMPLINGRATE_11_025;
            break;
        case 12000:
            rate = SL_SAMPLINGRATE_12;
            break;
        case 16000:
            rate = SL_SAMPLINGRATE_16;
            break;
        case 22050:
            rate = SL_SAMPLINGRATE_22_05;
            break;
        case 24000:
            rate = SL_SAMPLINGRATE_24;
            break;
        case 32000:
            rate = SL_SAMPLINGRATE_32;
            break;
        case 44100:
            rate = SL_SAMPLINGRATE_44_1;
            break;
        case 48000:
            rate = SL_SAMPLINGRATE_48;
            break;
        case 64000:
            rate = SL_SAMPLINGRATE_64;
            break;
        case 88200:
            rate = SL_SAMPLINGRATE_88_2;
            break;
        case 96000:
            rate = SL_SAMPLINGRATE_96;
            break;
        case 192000:
            rate = SL_SAMPLINGRATE_192;
            break;
        default:
            rate =  SL_SAMPLINGRATE_44_1;

    }
    return rate;
}

void TSAudio::setVolume(int percent) {
    if(pcmVolumePlay != NULL) {
        if (percent > 30) {
            (*pcmVolumePlay)->SetVolumeLevel(pcmVolumePlay, (100 - percent) * -20);
        } else if (percent > 25) {
            (*pcmVolumePlay)->SetVolumeLevel(pcmVolumePlay, (100 - percent) * -22);
        } else if (percent > 20) {
            (*pcmVolumePlay)->SetVolumeLevel(pcmVolumePlay, (100 - percent) * -25);
        } else if (percent > 15) {
            (*pcmVolumePlay)->SetVolumeLevel(pcmVolumePlay, (100 - percent) * -28);
        } else if (percent > 10) {
            (*pcmVolumePlay)->SetVolumeLevel(pcmVolumePlay, (100 - percent) * -30);
        } else if (percent > 5) {
            (*pcmVolumePlay)->SetVolumeLevel(pcmVolumePlay, (100 - percent) * -34);
        } else if (percent > 3) {
            (*pcmVolumePlay)->SetVolumeLevel(pcmVolumePlay, (100 - percent) * -37);
        } else if (percent > 0) {
            (*pcmVolumePlay)->SetVolumeLevel(pcmVolumePlay, (100 - percent) * -40);
        } else {
            (*pcmVolumePlay)->SetVolumeLevel(pcmVolumePlay, (100 - percent) * -100);
        }


    }
}

void TSAudio::pause() {
    if(pcmPlayerPlay != NULL)
    {
        (*pcmPlayerPlay)->SetPlayState(pcmPlayerPlay, SL_PLAYSTATE_PAUSED);
    }
}

void TSAudio::resume() {

    if(pcmPlayerPlay != NULL)
    {

        (*pcmPlayerPlay)->SetPlayState(pcmPlayerPlay, SL_PLAYSTATE_PLAYING);
    }


}

void TSAudio::setMute(int mute) {
    LOGE(" 声道  接口%p", pcmMutePlay);
    LOGE(" 声道  接口%d", mute);
    if(pcmMutePlay == NULL)
    {
        return;
    }
    this->mute = mute;
    if(mute == 0)//right   0   做通道播放
    {
        (*pcmMutePlay)->SetChannelMute(pcmMutePlay, 1, false);
        (*pcmMutePlay)->SetChannelMute(pcmMutePlay, 0, true);

    } else if(mute == 1)//left
    {
        (*pcmMutePlay)->SetChannelMute(pcmMutePlay, 1, true);
        (*pcmMutePlay)->SetChannelMute(pcmMutePlay, 0, false);
    }else if(mute == 2)//center
    {

        (*pcmMutePlay)->SetChannelMute(pcmMutePlay, 1, false);
        (*pcmMutePlay)->SetChannelMute(pcmMutePlay, 0, false);
    }

}

/**
 * 解码一帧数据
 * @return
 */
int TSAudio::resampleAudio() {
    LOGE("-------->resampleAudio1playstatus->exit %d",playstatus->exit);
    while (playstatus!=nullptr&&!playstatus->exit){
        LOGE("-------->resampleAudio1playstatus->exit %d",playstatus->exit);
        LOGE("-------->resampleAudio1 %d",queue->size());
        avPacket=av_packet_alloc();
//        if ()
        if (queue->getAvpacket(avPacket)!= 0){
            av_packet_free(&avPacket);
            av_free(avPacket);
            avPacket=nullptr;
            continue;
        }
        LOGE("-------->resampleAudio 1");
        ret = avcodec_send_packet(avCodecContext, avPacket);
        LOGE("-------->resampleAudio 2 %d",ret);
        if (ret!=0){
            av_packet_free(&avPacket);
            av_free(avPacket);
            avPacket=nullptr;
            continue;
        }
        LOGE("-------->resampleAudio 3");
        avFrame=av_frame_alloc();
        LOGE("-------->resampleAudio 4");
        ret=avcodec_receive_frame(avCodecContext,avFrame);
        if (ret==0){
            SwrContext *swr_ctx;
            swr_ctx= swr_alloc_set_opts(NULL,
                                        AV_CH_LAYOUT_STEREO,
                                        AV_SAMPLE_FMT_S16,
                                        avFrame->sample_rate,
                                        avFrame->channel_layout,
                                        (AVSampleFormat) avFrame->format,
                                        avFrame->sample_rate,
                                        NULL,NULL);
            if (!swr_ctx|| swr_init(swr_ctx)<0){
                av_packet_free(&avPacket);
                av_free(avPacket);
                avPacket = NULL;

                av_frame_free(&avFrame);
                av_free(avFrame);
                avFrame = NULL;

                swr_free(&swr_ctx);
                continue;

            }
            LOGE("-------->resampleAudio 5");
            int nb= swr_convert(swr_ctx,
                                &buffer,
                                avFrame->nb_samples,
                                (const uint8_t **)avFrame->data,
                                avFrame->nb_samples);
            int out_channels= av_get_channel_layout_nb_channels(AV_CH_LAYOUT_STEREO);

            data_size=nb*out_channels* av_get_bytes_per_sample(AV_SAMPLE_FMT_S16);
            LOGE("-------->resampleAudio 6");
            now_time=avFrame->pts* av_q2d(time_base);
            if (now_time<clock){
                now_time = clock;
            }
            clock=now_time;
            av_free(&avPacket);

            av_free(avPacket);
            LOGE("-------->resampleAudio 7");
            avPacket=nullptr;

            av_frame_free(&avFrame);

            av_free(avFrame);
            avFrame= nullptr;
            swr_free(&swr_ctx);
            break;
        }else{
            av_packet_free(&avPacket);
            av_free(avPacket);
            avPacket = nullptr;

            av_frame_free(&avFrame);
            av_free(avFrame);
            avFrame = nullptr;
            continue;
        }
    }
    return data_size;

}

void TSAudio::initOpenSLES() {
    SLresult result;
   //创建引擎
    result= slCreateEngine(&engineObject,0,0,0,0,0);

    if (result!=SL_RESULT_SUCCESS){
        return;
    }
    LOGE("-------->initOpenSLES  1 ");
    result=(*engineObject)->Realize(engineObject,SL_BOOLEAN_FALSE);
    (*engineObject)->GetInterface(engineObject,SL_IID_ENGINE,&engineEngine);

    if (result!=SL_RESULT_SUCCESS){
        return;
    }

    //创建混音器
    const SLInterfaceID mids[1]={SL_IID_ENVIRONMENTALREVERB};
    const SLboolean  mreg[1]={SL_BOOLEAN_FALSE};

    result=(*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 1,mids, mreg);
    if (result!=SL_RESULT_SUCCESS){
        return;
    }
//    初始化
    (*outputMixObject)->Realize(outputMixObject,SL_BOOLEAN_FALSE);
    if(result!=SL_RESULT_SUCCESS) {
        return;
    }


    result=(*outputMixObject)->GetInterface(outputMixObject,
                                            SL_IID_ENVIRONMENTALREVERB,
                                            &outputMixEnvironmentalReverb);
    if(result!=SL_RESULT_SUCCESS) {
        return;
    }


    SLDataFormat_PCM pcm={
            SL_DATAFORMAT_PCM,
            2,
            static_cast<SLuint32>(getCurrentSampleRateForOpensles(sample_rate)),
            SL_PCMSAMPLEFORMAT_FIXED_16,
            SL_PCMSAMPLEFORMAT_FIXED_16,
            SL_SPEAKER_FRONT_LEFT|SL_SPEAKER_FRONT_RIGHT,
            SL_BYTEORDER_LITTLEENDIAN
    };

    //    流数据
    SLDataLocator_AndroidSimpleBufferQueue android_queue={SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE,2};

    SLDataLocator_OutputMix outputMix={SL_DATALOCATOR_OUTPUTMIX,outputMixObject};

    SLDataSink audioSnk={&outputMix, 0};

    //   播放器跟混音器建立联系

    LOGE("-------->initOpenSLES 4 ");

    SLDataSource slDataSource={&android_queue, &pcm};

    const SLInterfaceID ids[3] = {SL_IID_BUFFERQUEUE,SL_IID_VOLUME,SL_IID_MUTESOLO};

    const SLboolean req[3] = {SL_BOOLEAN_TRUE,SL_BOOLEAN_TRUE,SL_BOOLEAN_TRUE};

    //创建播放对象
    (*engineEngine)->CreateAudioPlayer(engineEngine,&pcmPlayerObject,&slDataSource, &audioSnk,
                                       2,ids ,req);

    //初始化播放器
    (*pcmPlayerObject)->Realize(pcmPlayerObject, SL_BOOLEAN_FALSE);
  //  得到接口后调用  获取Player接口 //    得到接口后调用  获取Player接口
    (*pcmPlayerObject)->GetInterface(pcmPlayerObject,SL_IID_VOLUME,&pcmPlayerPlay);

    //是否静音接口
    (*pcmPlayerObject)->GetInterface(pcmPlayerObject, SL_IID_MUTESOLO, &pcmMutePlay);

    //   拿控制  播放暂停恢复的句柄
    (*pcmPlayerObject)->GetInterface(pcmPlayerObject,SL_IID_VOLUME,&pcmVolumePlay);
//    注册回调缓冲区 获取缓冲队列接口
    (*pcmPlayerObject)->GetInterface(pcmPlayerObject, SL_IID_BUFFERQUEUE, &pcmBufferQueue);


    //喇叭  你该怎么拉数据
    (*pcmBufferQueue)->RegisterCallback(pcmBufferQueue, pcmBufferCallBack, this);


    //    获取播放状态接口
    (*pcmPlayerPlay)->SetPlayState(pcmPlayerPlay, SL_PLAYSTATE_PLAYING);
    pcmBufferCallBack(pcmBufferQueue, this);
}
void *decodPlay(void *data) {
    TSAudio *mnAudio = (TSAudio *) data;
    mnAudio->initOpenSLES();
    pthread_exit(&mnAudio->thread_play);
}

void TSAudio::play() {
    pthread_create(&thread_play, NULL,decodPlay, this);

}


TSAudio::TSAudio(TSPlayerStatus *playstatus, int sample_rate, TsCallJava *callJava) {
    this->playstatus=playstatus;
    this->sample_rate=sample_rate;
    this->queue = new MNQueue(playstatus);
    buffer= (uint8_t *) av_malloc(sample_rate * 2 * 2);

}

